﻿using Microsoft.Extensions.Options;

namespace DimensionsHelper.Client.WinUi.Services;

public class OptionalFileService(ILocalSettingsService localSettingsService, IOptions<PresetOptions> presetOptions)
    : IOptionalFileService
{
    private const string SettingsKey = "OptionalFiles";
    private static Dictionary<string, OptionalFileStorage> _storages = [];
    private static bool _isSettingInitialized;
    private readonly PresetOptions _presetOptions = presetOptions.Value;
    private OptionalFileStorage? _storage;

    public string Key { get; set; } = string.Empty;


    public string StorageRoot => _storage?.Root ?? "";


    public async Task<IEnumerable<string>> GetHistoricalNamesAsync() => (await GetStorage()).History;


    public async Task<IEnumerable<string>> GetPresetNamesAsync() => (await GetStorage()).Preset;


    public async Task AddHistoryAsync(string jsonPath)
    {
        if ((await GetStorage()).AddHistory(NormalizePath(jsonPath)))
        {
            await SaveStorage();
        }
    }


    public async Task AddPresetAsync(string name)
    {
        if ((await GetStorage()).AddPreset(name))
        {
            await SaveStorage();
        }
    }


    public async Task<bool> IsHistoryAsync(string jsonPath) => (await GetStorage()).IsHistory(NormalizePath(jsonPath));


    public async Task<bool> IsPresetAsync(string jsonPath) => (await GetStorage()).IsPreset(jsonPath);


    public async Task RemoveHistoryAsync(string jsonPath)
    {
        if ((await GetStorage()).RemoveHistory(NormalizePath(jsonPath)))
        {
            await SaveStorage();
        }
    }


    public async Task ClearHistoryAsync()
    {
        OptionalFileStorage storage = await GetStorage();

        if (storage.HasHistory)
        {
            storage.RemoveAllHistory();
            await SaveStorage();
        }
    }


    public async Task RemovePresetAsync(string jsonPath)
    {
        if ((await GetStorage()).RemovePreset(NormalizePath(jsonPath)))
        {
            await SaveStorage();
        }
    }


    private async Task<OptionalFileStorage> GetStorage()
    {
        if (string.IsNullOrEmpty(Key))
        {
            throw new Exception("Property 'Key' is not set.");
        }

        if (!_isSettingInitialized)
        {
            string? settingContent = await localSettingsService.ReadSettingAsync(SettingsKey);
            // 如果未找到配置，添加预设配置
            if (!string.IsNullOrEmpty(settingContent))
            {
                try
                {
                    Dictionary<string, OptionalFileStorage>? data =
                        JsonSerializer.Deserialize<Dictionary<string, OptionalFileStorage>>(settingContent);

                    if (data != null)
                    {
                        _storages = data;
                    }
                }
                catch (Exception)
                {
                    // ignored
                }
            }

            // 如果存在未初始化的配置，添加默认值
            bool withMissingOptions = false;
            foreach ((string name, ProjectPresetOptions options) in _presetOptions.Projects)
            {
                withMissingOptions |= _storages.TryAdd(name, new OptionalFileStorage
                {
                    Root = options.Root,
                    Preset = options.Preset
                });
            }

            if (withMissingOptions)
            {
                await SaveStorage();
            }

            foreach ((string key, OptionalFileStorage storage) in _storages)
            {
                if (!_presetOptions.Projects.TryGetValue(key, out ProjectPresetOptions? presets))
                {
                    continue;
                }

                bool changed = false;
                // 如果未设置根路径，设置为默认值
                if (string.IsNullOrEmpty(storage.Root))
                {
                    storage.Root = presets.Root;
                    changed = true;
                }

                // 更新预设文件
                if (presets.Preset.Count > storage.Preset.Count)
                {
                    storage.Preset = presets.Preset;
                    changed = true;
                }

                if (changed)
                {
                    await SaveStorage();
                }
            }

            _isSettingInitialized = true;
        }

        _storage ??= _storages.GetValueOrDefault(Key);

        if (_storage == null)
        {
            _storage = new OptionalFileStorage();
            _storages.Add(Key, _storage);
            await SaveStorage();
        }

        return _storage;
    }


    private async Task SaveStorage()
    {
        if (string.IsNullOrEmpty(Key))
        {
            throw new Exception("Property 'Key' is not set.");
        }

        await localSettingsService.SaveSettingAsync(SettingsKey, _storages);
    }


    private static string NormalizePath(string path) => path.Replace('/', '\\');
}